package com.hina.rec.application.service.system.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hina.rec.application.convert.system.UserConvert;
import com.hina.rec.application.manager.system.UserManager;
import com.hina.rec.application.manager.system.UserRoleManager;
import com.hina.rec.application.service.system.UserService;
import com.hina.rec.common.model.IdReq;
import com.hina.rec.common.utils.AssertUtil;
import com.hina.rec.domain.model.UserDO;
import com.hina.rec.domain.model.UserRoleDO;
import com.hina.rec.endpoint.req.system.UserPageReq;
import com.hina.rec.endpoint.req.system.UserSaveReq;
import com.hina.rec.endpoint.req.system.UserSearchReq;
import com.hina.rec.endpoint.req.system.UserUpdateReq;
import com.hina.rec.endpoint.res.base.PageRes;
import com.hina.rec.endpoint.res.system.UserRes;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 用户管理Service实现类
 *
 * @author liaosp
 * @date 2024-01-10
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserManager userManager;
    private final UserRoleManager userRoleManager;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean save(UserSaveReq req) {
        UserDO userDO = UserConvert.INSTANCE.toUserDO(req);
        boolean exists = userManager.lambdaQuery().eq(UserDO::getUsername, req.getUsername()).exists();
        AssertUtil.isFalse(exists, "用户已存在");
        userManager.save(userDO);
        saveOrUpdateUserRole(userDO.getId(), req.getRoleIds());
        return true;
    }


    /**
     * 保存或更新用户角色关联
     *
     * @param userId
     * @param roleIds
     */
    private void saveOrUpdateUserRole(Integer userId, List<Integer> roleIds) {
        AssertUtil.notEmpty(roleIds, "角色不能为空");
        // 批量保存新的角色关联
        List<UserRoleDO> userRoleList = roleIds.stream()
                .map(roleId -> {
                    UserRoleDO userRole = new UserRoleDO();
                    userRole.setUserId(userId);
                    userRole.setRoleId(roleId);
                    return userRole;
                })
                .toList();
        userRoleManager.saveBatch(userRoleList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(UserUpdateReq req) {
        UserDO idUser = userManager.getById(req.getId());
        AssertUtil.notNull(idUser, "用户不存在!");
        UserDO userDO = UserConvert.INSTANCE.toUserDO(req);
        return userManager.updateById(userDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Integer id) {
        // 删除用户
        return userManager.removeById(id);
    }

    @Override
    public PageRes<UserRes> page(UserPageReq req) {
        Page<UserDO> page = new Page<>(req.getPageNum(), req.getPageSize());
        page = userManager.page(page);
        return PageRes.fromPage(page, UserConvert.INSTANCE::toUserRes);
    }

    @Override
    public List<UserRes> search(UserSearchReq req) {
        List<UserDO> userList = userManager.lambdaQuery()
                .like(StringUtils.isNotBlank(req.getUsername()), UserDO::getUsername, req.getUsername())
                .like(StringUtils.isNotBlank(req.getRealName()), UserDO::getRealName, req.getRealName())
                .eq(req.getStatus() != null, UserDO::getStatus, req.getStatus())
                .orderByAsc(UserDO::getId)
                .list();
        return UserConvert.INSTANCE.toUserResList(userList);
    }

    @Override
    public List<UserRes> simpleList() {
        // 只查询启用状态的用户
        List<UserDO> userList = userManager.lambdaQuery()
                .eq(UserDO::getStatus, true)
                .select(UserDO::getId, UserDO::getUsername)
                .orderByAsc(UserDO::getId)
                .list();
        return UserConvert.INSTANCE.toSimpleUserResList(userList);
    }

    @Override
    public UserRes detail(IdReq req) {
        UserDO userDO = userManager.getById(req.getId());
        List<UserRoleDO> roleList = userRoleManager.lambdaQuery().eq(UserRoleDO::getUserId, req.getId())
                .list();
        UserRes userRes = UserConvert.INSTANCE.toUserRes(userDO);
        userRes.setRoleIds(CollUtil.isEmpty(roleList) ? null : roleList.stream().map(UserRoleDO::getRoleId).toList());
        return userRes;
    }
}